]> dgit.raspbian.org Git - gnome-shell.git/commitdiff
extensionSystem: Support locking down extension installation
authorFlorian Müllner <fmuellner@gnome.org>
Fri, 9 Feb 2024 23:58:27 +0000 (00:58 +0100)
committerMarge Bot <marge-bot@gnome.org>
Wed, 14 Feb 2024 16:20:59 +0000 (16:20 +0000)
Currently extensions can only be locked down completely by
restricting the `enabled-extensions` key via dconf.

This is too restrictive for environments that want to allow users
to customize their system with extensions, while still limiting
the set of possible extensions.

To fill that gap, add a new `allow-extension-installation` setting,
which restricts extensions to system extensions when disabled.

As the setting is mainly intended for locking down by system
administrators, there is no attempt to load/unload extensions
on settings changes.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/3180>

data/org.gnome.shell.gschema.xml.in
js/misc/dbusErrors.js
js/ui/extensionDownloader.js
js/ui/extensionSystem.js

index f4fa86d013a2ccfbe4730c26c0cf6141b355809f..4ddc6a1195f584f272a074cadffd37ce49747a9f 100644 (file)
         the “enabled-extension” setting.
       </description>
     </key>
+    <key name="allow-extension-installation" type="b">
+      <default>true</default>
+      <summary>Allow extension installation</summary>
+      <description>
+        Allow users to install extensions in their home folder. If disabled,
+        the InstallRemoteExtension D-Bus method will fail, and extensions
+        are only loaded from system directories on startup.
+        It does not affect extensions that are already loaded, so a change
+        only takes full effect on the next login.
+      </description>
+    </key>
     <key name="disable-extension-version-validation" type="b">
       <default>false</default>
       <summary>Disables the validation of extension version compatibility</summary>
index 6f4f80b51a42009eda9870afeff47d1adcb59163..ec726e89c2c0c53144d7baa935096d7677ba2f32 100644 (file)
@@ -40,6 +40,7 @@ export const ExtensionError = {
     DOWNLOAD_FAILED: 1,
     EXTRACT_FAILED: 2,
     ENABLE_FAILED: 3,
+    NOT_ALLOWED: 4,
 };
 export const ExtensionErrors =
     registerErrorDomain('Extensions', ExtensionError);
index 6486bbcada752886f0ef028351d371d4e17746a0..33f168ce6ca5a0a807f63625f2dfc4c654519afc 100644 (file)
@@ -32,6 +32,13 @@ let _httpSession;
  * @returns {void}
  */
 export async function installExtension(uuid, invocation) {
+    if (!global.settings.get_boolean('allow-extension-installation')) {
+        invocation.return_error_literal(
+            ExtensionErrors, ExtensionError.NOT_ALLOWED,
+            'Extension installation is not allowed');
+        return;
+    }
+
     const params = {
         uuid,
         shell_version: Config.PACKAGE_VERSION,
index 07be8066cb50268e398cc2e74b0b10da7d941857..76ae58ff4e4b91b09d5dba045ea33ce50fae306f 100644 (file)
@@ -86,8 +86,11 @@ export class ExtensionManager extends Signals.EventEmitter {
 
     get updatesSupported() {
         const appSys = Shell.AppSystem.get_default();
-        return (appSys.lookup_app('org.gnome.Extensions.desktop') !== null) ||
-               (appSys.lookup_app('com.mattjakeman.ExtensionManager.desktop') !== null);
+        const hasUpdatesApp =
+            appSys.lookup_app('org.gnome.Extensions.desktop') !== null ||
+            appSys.lookup_app('com.mattjakeman.ExtensionManager.desktop') !== null;
+        const allowed = global.settings.get_boolean('allow-extension-installation');
+        return allowed && hasUpdatesApp;
     }
 
     lookup(uuid) {
@@ -745,7 +748,8 @@ export class ExtensionManager extends Signals.EventEmitter {
 
         let perUserDir = Gio.File.new_for_path(global.userdatadir);
 
-        const extensionFiles = [...FileUtils.collectFromDatadirs('extensions', true)];
+        const includeUserDir = global.settings.get_boolean('allow-extension-installation');
+        const extensionFiles = [...FileUtils.collectFromDatadirs('extensions', includeUserDir)];
         const extensionObjects = extensionFiles.map(({dir, info}) => {
             let fileType = info.get_file_type();
             if (fileType !== Gio.FileType.DIRECTORY)